#!/usr/bin/python
import re
import struct

#******************************************************************************
# File: 
#		python.py
# Recipe: 1.1
#		Accessing Substrings
# Version:
#		0.1
# Author:
#   	Yubei Zhu
# Mail:
#		yubeizhu@gmail.com
# Created at:
#   	2012-08-14  
# Last Update:
#   	2012-08-15
# License: 
#		GPLv3	
#******************************************************************************


########################## Access of substring ###########################
# Index   +012345678901234567890
string =  "This is what you have"
# R-Index  109876543210987654321-

# Index
first = string[ 0 ]   		
last  = string[ -1 ]

# range / slice
piece =  string[ 5 : 7 ]  		# is
rpiece = string[ -8 : -5 ]  	# reverse piece: you 

rest = string[ 13: ]; 			# you have
rrest = string[ -4: ]  			# reverse piece: have   

########################## Modify of substring ############################
# Convert str to list
strlist = list( string ) 
strlist[ 5 : 7 ] = "wasn't"
strlist[ -12 : ] = "ondrous"
strlist[ 0 ] = ""
strlist[ -10 : ] = ""
string = "".join( strlist )
print "Modify of string %s:" % string

########################## Pattern match/ Substitution of substring #########
string =  "This is what you have"
print "String now: " + string

# str method
if string.find( "have", -10 ) != -1:
	print "Pattern matches in last 10 characters"

# regular expression, use re module
result = re.search( "have", string[ -10 : ] )
if result:
	print "Pattern matches in last 10 characters"

string = string[ 0 : 4 ].replace("is","at") + string[ 4 : ] # replace method
print "String after substitution: %s" % string

######################### Swap of substring ####################################
# Recipe 1.3 Exchanging Values Without Using Temporary Variables
string = "make a hat"
print "Before swap: %s" % string
strlist = list( string )
strlist[ 0 ],strlist[ -1 ] = strlist[ -1 ], strlist[ 0 ]
string = "".join( strlist )
print "After swap:  %s" % string	


########################## Substring using unpack ###############################
def unpack( baseformat, string, rest = False ):
	''' 
PURPOSE: 
	unpack in string from a string.
USAGE:   
	unpack( " 6x 6s ", string )
	unpack( " 6x 6s ", string, True )	
PASSED ARGS:  
	1. str: format string
	2. str: content of the string
	3. get rest bytes or skip rest bytes, skip by default
RETURN ARGS:
	str/list: sub strings
Error - Fail Error Message
	None
	'''
	# cal the rest byte number from the format string
	numremain = len( string ) - struct.calcsize( baseformat )
	
	# Create the format for struct.unpack()
	# By default we skip the rest of the bytes
	format = " %s %d%s "  %( baseformat, numremain, rest and "s" or "x" ) 
	return struct.unpack( format, string )	


def cut2fmt( poslist, string, rest = False  ):
	''' 
PURPOSE: 
	convert the postions cut in string to a format string for unpack.
USAGE:   
	cut2fmt( [ 8,14 ], string )
	cut2fmt( [ 8,14 ], string, True )	
PASSED ARGS:  
	1. list: postions want to be cut
	2. str: content of the string
	3. get rest bytes or skip rest bytes, skip by default
RETURN ARGS:
	str: format string
Error - Fail Error Message
	None
	'''
	poslist = [ 1 ] + poslist
	baseformats = [ "%ds" % ( poslist[ i + 1 ] - poslist[ i ] )\
								for i in ( range( len( poslist ) - 1 ) ) ]	
	baseformat = " ".join(baseformats)
	numremain = len( string ) - struct.calcsize( baseformat )
	format = "%s %d%s"  %( baseformat, numremain, rest and "s" or "x" ) 
	return format

# Usage Example
string = "To be or not to be"
unpackstr = unpack( "6x 6s", string )
print "After unpack: %s" % unpackstr

strings =  unpack( "2s 1x 2s 1x ", string )
print "Multiple strings", strings;


format = cut2fmt( [ 8, 14 ], string)
print "Format String: [%s]" % format

	 
